﻿using RemoteSensingImageDirectServer.Models.Request.Listener;
using RemoteSensingImageDirectServer.Models.Request.Response;
using RemoteSensingImageDirectServer.Untils;
using RemoteSensingImageDirectServer.Untils.Extensions;
using RemoteSensingImageDirectServer.Untils.Pool;
using RemoteSensingImageDirectServer.Untils.Source;
using System;
using System.Security.AccessControl;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace RemoteSensingImageDirectServer.Service.OGC.Metadata
{
    public class RasterMapMetadata : IRasterMapMetadata
    {
        /// <summary>
        /// 配置表
        /// </summary>
        private readonly IConfiguration _configuration;

        public RasterMapMetadata(IConfiguration configuration)
        {
            this._configuration = configuration;
        }

        public ServiceResult GetCapabilities(IRSIMapSource source, ICapabilitiesListener listener,
            string? capabilitiesUri, string? tileUri, string? aliasName = null)
        {
           
            XmlDocument doc = new XmlDocument();

            if (listener.Service.ToUpper() == "WMS")
            {
                var wmsBuilder = GetWMS(source, listener, capabilitiesUri, tileUri, aliasName);
                doc.LoadXml(wmsBuilder);
            }
            else
            {
                var wmtsBuilder = GetWMTS(source, listener, capabilitiesUri, tileUri, aliasName);
                doc.LoadXml(wmtsBuilder);
            }
            ServiceResult serviceResult = new ServiceResult(0);
            serviceResult.Data = doc;
            return serviceResult;
        }

        public ServiceResult GetCapabilitiesForSuperMap(IRSIMapSource source, ICapabilitiesListener listener, 
            string? capabilitiesUri, string? tileUri, string? aliasName = null)
        {
            XmlDocument doc = new XmlDocument();

            var wmtsBuilder = GetSuperMapWMTS(source, listener, capabilitiesUri, tileUri, aliasName);
            doc.LoadXml(wmtsBuilder);

            ServiceResult serviceResult = new ServiceResult(0);
            serviceResult.Data = doc;
            return serviceResult;
        }

        private string GetWMS(IRSIMapSource source, ICapabilitiesListener listener,
            string? capabilitiesUri, string? tileUri, string? aliasName = null)
        {
            IWMSListener wmsListener = (IWMSListener)listener;
            var dstExtent = source.GetDstRasterEnvelope();
            var epsgCode = source.GetDstEPSG();
            var wgs84Extent = source.GetDstDataset().GetWGS84RasterEnvelope();

            var builder = new StringBuilder();
            builder.AppendLine("<?xml version =\"1.0\" encoding=\"UTF-8\"?>");
            builder.AppendLine("<!DOCTYPE WMT_MS_Capabilities SYSTEM \"http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd\">");
            builder.AppendLine($"<WMT_MS_Capabilities version=\"{listener.Version}\">");
            builder.AppendLine("<Service>");
            builder.AppendLine($"<Name>{_configuration.GetValue<string>("WMS:Name")}-EPSG-{epsgCode}</Name>");
            builder.AppendLine($"<Title>{_configuration.GetValue<string>("WMS:Title")}-EPSG-{epsgCode}</Title>");
            builder.AppendLine($"<Abstract>{_configuration.GetValue<string>("WMS:Abstract")}</Abstract>");
            builder.AppendLine($"<OnlineResource xmlns:xlink=\"http://www.w3.org/1999/xlink\" xlink:type=\"simple\" xlink:href=\"{_configuration.GetValue<string>("WMS:OfficialWebsite")}\" />");
            builder.AppendLine("<ContactInformation>");
            builder.AppendLine("<ContactPersonPrimary>");
            builder.AppendLine($"<ContactPerson>{_configuration.GetValue<string>("WMS:ContactPerson")}</ContactPerson>");
            builder.AppendLine($"<ContactOrganization>{_configuration.GetValue<string>("WMS:ContactOrganization")}</ContactOrganization>");
            builder.AppendLine("</ContactPersonPrimary>");
            builder.AppendLine($"<ContactPosition>{_configuration.GetValue<string>("WMS:ContactPosition")}</ContactPosition>");
            builder.AppendLine("<ContactAddress>");
            builder.AppendLine($"<AddressType>{_configuration.GetValue<string>("WMS:AddressType")}</AddressType>");
            builder.AppendLine($"<Address>{_configuration.GetValue<string>("WMS:Address")}</Address>");
            builder.AppendLine($"<City>{_configuration.GetValue<string>("WMS:City")}</City>");
            builder.AppendLine($"<StateOrProvince>{_configuration.GetValue<string>("WMS:StateOrProvince")}</StateOrProvince>");
            builder.AppendLine($"<PostCode>{_configuration.GetValue<string>("WMS:PostCode")}</PostCode>");
            builder.AppendLine($"<Country>{_configuration.GetValue<string>("WMS:Country")}</Country>");
            builder.AppendLine("</ContactAddress>");
            builder.AppendLine($"<ContactVoiceTelephone>{_configuration.GetValue<string>("WMS:ContactVoiceTelephone")}</ContactVoiceTelephone>");
            builder.AppendLine($"<ContactFacsimileTelephone>{_configuration.GetValue<string>("WMS:ContactFacsimileTelephone")}</ContactFacsimileTelephone>");
            builder.AppendLine($"<ContactElectronicMailAddress>{_configuration.GetValue<string>("WMS:ContactElectronicMailAddress")}</ContactElectronicMailAddress>");
            builder.AppendLine("</ContactInformation>");
            builder.AppendLine("<Fees>NONE</Fees>");
            builder.AppendLine("<AccessConstraints>NONE</AccessConstraints>");
            builder.AppendLine("</Service>");
            builder.AppendLine("<Capability>");
            builder.AppendLine("<Request>");
            builder.AppendLine("<GetCapabilities>");
            builder.AppendLine("<Format>application/vnd.ogc.wms_xml</Format>");
            builder.AppendLine("<Format>text/xml</Format>");
            builder.AppendLine("<DCPType>");
            builder.AppendLine("<HTTP>");
            builder.AppendLine("<Get>");
            builder.AppendLine($"<OnlineResource xmlns:xlink=\"http://www.w3.org/1999/xlink\" xlink:type=\"simple\" xlink:href=\"{capabilitiesUri}\" />");
            builder.AppendLine("</Get>");
            builder.AppendLine("</HTTP>");
            builder.AppendLine("</DCPType>");
            builder.AppendLine("</GetCapabilities>");
            builder.AppendLine("<GetMap>");
            builder.AppendLine("<Format>image/png</Format>");
            builder.AppendLine("<DCPType>");
            builder.AppendLine("<HTTP>");
            builder.AppendLine("<Get>");
            builder.AppendLine($"<OnlineResource xmlns:xlink=\"http://www.w3.org/1999/xlink\" xlink:type=\"simple\" xlink:href=\"{tileUri}\" />");
            builder.AppendLine("</Get>");
            builder.AppendLine("</HTTP>");
            builder.AppendLine("</DCPType>");
            builder.AppendLine("</GetMap>");
            builder.AppendLine("</Request>");
            builder.AppendLine("<Exception>");
            builder.AppendLine("<Format>application/vnd.ogc.se_xml</Format>");
            builder.AppendLine("<Format>application/vnd.ogc.se_inimage</Format>");
            builder.AppendLine("<Format>application/vnd.ogc.se_blank</Format>");
            builder.AppendLine("</Exception>");
            builder.AppendLine("<Layer>");

            builder.AppendLine($"<Title>{_configuration.GetValue<string>("WMS:ServiceTitle")}</Title>");
            builder.AppendLine($"<Abstract>{_configuration.GetValue<string>("WMS:ServiceAbstract")}</Abstract>");
            builder.AppendLine($"<SRS>EPSG:{epsgCode}</SRS>");

            builder.AppendLine($"<LatLonBoundingBox minx=\"{wgs84Extent.MinX}\" miny=\"{wgs84Extent.MinY}\" maxx=\"{wgs84Extent.MaxX}\" maxy=\"{wgs84Extent.MaxY}\" />");
            builder.AppendLine("<Layer>");
            builder.AppendLine($"<Title>{aliasName ?? wmsListener.Layers}</Title>");
            builder.AppendLine($"<Name>{aliasName ?? wmsListener.Layers}</Name>");
            builder.AppendLine("<Abstract></Abstract>");
            builder.AppendLine($"<SRS>EPSG:{epsgCode}</SRS>");
            builder.AppendLine($"<LatLonBoundingBox minx=\"{wgs84Extent.MinX}\" miny=\"{wgs84Extent.MinY}\" maxx=\"{wgs84Extent.MaxX}\" maxy=\"{wgs84Extent.MaxY}\" />");
            builder.AppendLine($"<BoundingBox SRS=\"EPSG:{epsgCode}\" minx=\"{dstExtent.MinX}\" miny=\"{dstExtent.MinY}\" maxx=\"{dstExtent.MaxX}\" maxy=\"{dstExtent.MaxY}\" />");
            builder.AppendLine("</Layer>");
            builder.AppendLine("</Layer>");
            builder.AppendLine("</Capability>");
            builder.AppendLine("</WMT_MS_Capabilities>");
            return builder.ToString();
        }

        private string GetWMTS(IRSIMapSource source, ICapabilitiesListener listener,
            string? capabilitiesUri, string? tileUri, string? aliasName = null)
        {
            IWMTSListener wmtsListener = (IWMTSListener)listener;
            var dstExtent = source.GetDstRasterEnvelope();
            var epsgCode = source.GetDstEPSG();
            var wgs84Extent = source.GetDstDataset().GetWGS84RasterEnvelope();

            var builder = new StringBuilder();
            builder.AppendLine("<?xml version =\"1.0\" encoding=\"UTF-8\"?>");
            builder.AppendLine("<Capabilities xmlns=\"http://www.opengis.net/wmts/1.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:gml=\"http://www.opengis.net/gml\" xsi:schemaLocation=\"http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd\" version=\"1.0.0\">");
            builder.AppendLine("<ows:ServiceIdentification>");
            builder.AppendLine($"<ows:Title>{_configuration.GetValue<string>("WMTS:Title")}-EPSG-{epsgCode}</ows:Title>");
            builder.AppendLine($"<ows:ServiceType>{_configuration.GetValue<string>("WMTS:ServiceType")}</ows:ServiceType>");
            builder.AppendLine("<ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>");
            builder.AppendLine("<ows:Fees>none</ows:Fees>");
            builder.AppendLine("<ows:AccessConstraints>none</ows:AccessConstraints>");
            builder.AppendLine("</ows:ServiceIdentification>");
            builder.AppendLine("<ows:ServiceProvider>");
            builder.AppendLine($"<ows:ProviderName>{_configuration.GetValue<string>("WMTS:ProviderName")}</ows:ProviderName>");
            builder.AppendLine($"<ows:ProviderSite xlink:href=\"{_configuration.GetValue<string>("WMTS:OfficialWebsite")}\">{_configuration.GetValue<string>("WMTS:OfficialWebsite")}</ows:ProviderSite>");
            builder.AppendLine("<ows:ServiceContact>");
            builder.AppendLine($"<ows:IndividualName>{_configuration.GetValue<string>("WMTS:IndividualName")}</ows:IndividualName>");
            builder.AppendLine($"<ows:PositionName>{_configuration.GetValue<string>("WMTS:PositionName")}</ows:PositionName>");
            builder.AppendLine("<ows:ContactInfo>");
            builder.AppendLine("<ows:Phone>");
            builder.AppendLine($"<ows:Voice>{_configuration.GetValue<string>("WMTS:Voice")}</ows:Voice>");
            builder.AppendLine($"<ows:Facsimile>{_configuration.GetValue<string>("WMTS:Facsimile")}</ows:Facsimile>");
            builder.AppendLine("</ows:Phone>");
            builder.AppendLine("<ows:Address>");
            builder.AppendLine($"<ows:DeliveryPoint>{_configuration.GetValue<string>("WMTS:DeliveryPoint")}</ows:DeliveryPoint>");
            builder.AppendLine($"<ows:City>{_configuration.GetValue<string>("WMTS:City")}</ows:City>");
            builder.AppendLine($"<ows:AdministrativeArea>{_configuration.GetValue<string>("WMTS:AdministrativeArea")}</ows:AdministrativeArea>");
            builder.AppendLine("<ows:PostalCode />");
            builder.AppendLine($"<ows:Country>{_configuration.GetValue<string>("WMTS:Country")}</ows:Country>");
            builder.AppendLine($"<ows:ElectronicMailAddress>{_configuration.GetValue<string>("WMTS:ElectronicMailAddress")}</ows:ElectronicMailAddress>");
            builder.AppendLine("</ows:Address>");
            builder.AppendLine("</ows:ContactInfo>");
            builder.AppendLine("</ows:ServiceContact>");
            builder.AppendLine("</ows:ServiceProvider>");
            builder.AppendLine("<ows:OperationsMetadata>");
            builder.AppendLine("<ows:Operation name=\"GetCapabilities\">");
            builder.AppendLine("<ows:DCP>");
            builder.AppendLine("<ows:HTTP>");
            builder.AppendLine($"<ows:Get xlink:href=\"{capabilitiesUri}\">");
            builder.AppendLine("<ows:Constraint name=\"GetEncoding\">");
            builder.AppendLine("<ows:AllowedValues>");
            builder.AppendLine("<ows:Value>KVP</ows:Value>");
            builder.AppendLine("</ows:AllowedValues>");
            builder.AppendLine("</ows:Constraint>");
            builder.AppendLine("</ows:Get>");
            builder.AppendLine("</ows:HTTP>");
            builder.AppendLine("</ows:DCP>");
            builder.AppendLine("</ows:Operation>");
            builder.AppendLine("<ows:Operation name=\"GetTile\">");
            builder.AppendLine("<ows:DCP>");
            builder.AppendLine("<ows:HTTP>");
            builder.AppendLine($"<ows:Get xlink:href=\"{tileUri}\">");
            builder.AppendLine("<ows:Constraint name=\"GetEncoding\">");
            builder.AppendLine("<ows:AllowedValues>");
            builder.AppendLine("<ows:Value>KVP</ows:Value>");
            builder.AppendLine("</ows:AllowedValues>");
            builder.AppendLine("</ows:Constraint>");
            builder.AppendLine("</ows:Get>");
            builder.AppendLine("</ows:HTTP>");
            builder.AppendLine("</ows:DCP>");
            builder.AppendLine("</ows:Operation>");
            builder.AppendLine("</ows:OperationsMetadata>");
            builder.AppendLine("<Contents>");
            builder.AppendLine("<Layer>");
            builder.AppendLine($"<ows:Title>{aliasName ?? wmtsListener.Layer}</ows:Title>");
            builder.AppendLine($"<ows:Abstract>img</ows:Abstract>");//WMTS service under the OGC standard
            builder.AppendLine($"<ows:Identifier>{wmtsListener.Layer}</ows:Identifier>");
            builder.AppendLine("<ows:WGS84BoundingBox>");

            builder.AppendLine($"<ows:LowerCorner>{wgs84Extent.MinX} {wgs84Extent.MinY}</ows:LowerCorner>");
            builder.AppendLine($"<ows:UpperCorner>{wgs84Extent.MaxX} {wgs84Extent.MaxY}</ows:UpperCorner>");
            builder.AppendLine("</ows:WGS84BoundingBox>");

            if (epsgCode != 4326 && epsgCode != 4490)
            {
                builder.AppendLine($"<ows:BoundingBox>");
                builder.AppendLine($"<ows:LowerCorner>{dstExtent.MinX} {dstExtent.MinY}</ows:LowerCorner>");
                builder.AppendLine($"<ows:UpperCorner>{dstExtent.MaxX} {dstExtent.MaxY}</ows:UpperCorner>");
                builder.AppendLine("</ows:BoundingBox>");
            }

            builder.AppendLine("<Style isDefault=\"true\">");
            builder.AppendLine("<ows:Title>Default Style</ows:Title>");
            builder.AppendLine("<ows:Identifier>default</ows:Identifier>");
            builder.AppendLine("</Style>");
            builder.AppendLine($"<Format>{_configuration.GetValue<string>("WMTS:Format")}</Format>");
            builder.AppendLine("<TileMatrixSetLink>");
            builder.AppendLine($"<TileMatrixSet>EPSG:{epsgCode}</TileMatrixSet>");
            builder.AppendLine("</TileMatrixSetLink>");
            builder.AppendLine("</Layer>");
            builder.AppendLine("<TileMatrixSet>");
            builder.AppendLine($" <ows:Title>EPSG:{epsgCode}</ows:Title>");
            builder.AppendLine($"<ows:Abstract>EPSG:{epsgCode}</ows:Abstract>");
            builder.AppendLine($"<ows:Identifier>EPSG:{epsgCode}</ows:Identifier>");
            builder.AppendLine($"<ows:SupportedCRS>{_configuration.GetValue<string>("WMTS:TileMatrixSetSupportedCRS")}{epsgCode}</ows:SupportedCRS>");

            string TopLeftCorner = null;
            if (epsgCode.Equals(4326) || epsgCode.Equals(4490))
            {
                TopLeftCorner = "90.0 -180.0";
                for (int level = _configuration.GetValue<int>("WMTS:LevelMin"); level < _configuration.GetValue<int>("WMTS:LevelMax"); level++)
                {
                    builder.AppendLine("<TileMatrix>");
                    builder.AppendLine($"<ows:Identifier>{level}</ows:Identifier>");
                    builder.AppendLine($"<ScaleDenominator>{TileResTierPool.Instance().TileScaleDenominator[level]}</ScaleDenominator>");
                    //builder.AppendLine($"<!-- <Resolution>{TileResTierPool.Instance().Wgs84Levels[level]}</Resolution> -->");
                    builder.AppendLine($"<TopLeftCorner>{TopLeftCorner}</TopLeftCorner>");
                    builder.AppendLine($"<TileWidth>{_configuration.GetValue<int>("WMTS:TileWidth")}</TileWidth>");
                    builder.AppendLine($"<TileHeight>{_configuration.GetValue<int>("WMTS:TileHeight")}</TileHeight>");
                    builder.AppendLine($"<MatrixWidth>{Math.Pow(2, level + 1)}</MatrixWidth>");
                    builder.AppendLine($"<MatrixHeight>{Math.Pow(2, level)}</MatrixHeight>");
                    builder.AppendLine("</TileMatrix>");
                }
            }
            else if (epsgCode.Equals(3857))
            {
                TopLeftCorner = "-20037508.3427892 20037508.3427892";
                for (int level = _configuration.GetValue<int>("WMTS:LevelMin"); level < _configuration.GetValue<int>("WMTS:LevelMax"); level++)
                {
                    builder.AppendLine("<TileMatrix>");
                    builder.AppendLine($"<ows:Identifier>{level}</ows:Identifier>");
                    builder.AppendLine($"<ScaleDenominator>{TileResTierPool.Instance().TileScaleDenominator[level]}</ScaleDenominator>");
                    //builder.AppendLine($"<!-- <Resolution>{TileResTierPool.Instance().MercatorLevels[level]}</Resolution> -->");
                    builder.AppendLine($"<TopLeftCorner>{TopLeftCorner}</TopLeftCorner>");
                    builder.AppendLine($"<TileWidth>{_configuration.GetValue<int>("WMTS:TileWidth")}</TileWidth>");
                    builder.AppendLine($"<TileHeight>{_configuration.GetValue<int>("WMTS:TileHeight")}</TileHeight>");
                    builder.AppendLine($"<MatrixWidth>{Math.Pow(2, level)}</MatrixWidth>");
                    builder.AppendLine($"<MatrixHeight>{Math.Pow(2, level)}</MatrixHeight>");
                    builder.AppendLine("</TileMatrix>");
                }
            }
            else
            {
                TopLeftCorner = $"{dstExtent.MaxY} {dstExtent.MinX}";
                for (int level = _configuration.GetValue<int>("WMTS:LevelMin"); level < _configuration.GetValue<int>("WMTS:LevelMax"); level++)
                {
                    var tileWidth = _configuration.GetValue<int>("WMTS:TileWidth");
                    var tileHeight = _configuration.GetValue<int>("WMTS:TileHeight");
                    var MatrixWidth = (int)Math.Ceiling((dstExtent.MaxX - dstExtent.MinX) / (tileWidth * TileResTierPool.Instance().MercatorLevels[level]));
                    var MatrixHeight = (int)Math.Ceiling((dstExtent.MaxY - dstExtent.MinY) / (tileHeight * TileResTierPool.Instance().MercatorLevels[level]));

                    builder.AppendLine("<TileMatrix>");
                    builder.AppendLine($"<ows:Identifier>{level}</ows:Identifier>");
                    builder.AppendLine($"<ScaleDenominator>{TileResTierPool.Instance().TileScaleDenominator[level]}</ScaleDenominator>");
                    //builder.AppendLine($"<!-- <Resolution>{TileResTierPool.Instance().MercatorLevels[level]}</Resolution> -->");
                    builder.AppendLine($"<TopLeftCorner>{TopLeftCorner}</TopLeftCorner>");
                    builder.AppendLine($"<TileWidth>{tileWidth}</TileWidth>");
                    builder.AppendLine($"<TileHeight>{tileHeight}</TileHeight>");
                    builder.AppendLine($"<MatrixWidth>{MatrixWidth}</MatrixWidth>");
                    builder.AppendLine($"<MatrixHeight>{MatrixHeight}</MatrixHeight>");
                    builder.AppendLine("</TileMatrix>");
                }
            }

            builder.AppendLine("</TileMatrixSet>");
            builder.AppendLine("</Contents>");
            builder.AppendLine("</Capabilities>");

            return builder.ToString();
        }

        private string GetSuperMapWMTS(IRSIMapSource source, ICapabilitiesListener listener,
          string? capabilitiesUri, string? tileUri, string? aliasName = null)
        {
            IWMTSListener wmtsListener = (IWMTSListener)listener;
            var dstExtent = source.GetDstRasterEnvelope();
            var epsgCode = source.GetDstEPSG();
            var wgs84Extent = source.GetDstDataset().GetWGS84RasterEnvelope();

            var builder = new StringBuilder();
            builder.AppendLine("<?xml version =\"1.0\" encoding=\"UTF-8\"?>");
            builder.AppendLine("<Capabilities xmlns=\"http://www.opengis.net/wmts/1.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:gml=\"http://www.opengis.net/gml\" xsi:schemaLocation=\"http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd\" version=\"1.0.0\">");
            builder.AppendLine("<ows:ServiceIdentification>");
            builder.AppendLine($"<ows:Title>{_configuration.GetValue<string>("WMTS:Title")}-EPSG-{epsgCode}</ows:Title>");
            builder.AppendLine($"<ows:ServiceType>{_configuration.GetValue<string>("WMTS:ServiceType")}</ows:ServiceType>");
            builder.AppendLine("<ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>");
            builder.AppendLine("<ows:Fees>none</ows:Fees>");
            builder.AppendLine("<ows:AccessConstraints>none</ows:AccessConstraints>");
            builder.AppendLine("</ows:ServiceIdentification>");
            builder.AppendLine("<ows:ServiceProvider>");
            builder.AppendLine($"<ows:ProviderName>{_configuration.GetValue<string>("WMTS:ProviderName")}</ows:ProviderName>");
            builder.AppendLine($"<ows:ProviderSite xlink:href=\"{_configuration.GetValue<string>("WMTS:OfficialWebsite")}\">{_configuration.GetValue<string>("WMTS:OfficialWebsite")}</ows:ProviderSite>");
            builder.AppendLine("<ows:ServiceContact>");
            builder.AppendLine($"<ows:IndividualName>{_configuration.GetValue<string>("WMTS:IndividualName")}</ows:IndividualName>");
            builder.AppendLine($"<ows:PositionName>{_configuration.GetValue<string>("WMTS:PositionName")}</ows:PositionName>");
            builder.AppendLine("<ows:ContactInfo>");
            builder.AppendLine("<ows:Phone>");
            builder.AppendLine($"<ows:Voice>{_configuration.GetValue<string>("WMTS:Voice")}</ows:Voice>");
            builder.AppendLine($"<ows:Facsimile>{_configuration.GetValue<string>("WMTS:Facsimile")}</ows:Facsimile>");
            builder.AppendLine("</ows:Phone>");
            builder.AppendLine("<ows:Address>");
            builder.AppendLine($"<ows:DeliveryPoint>{_configuration.GetValue<string>("WMTS:DeliveryPoint")}</ows:DeliveryPoint>");
            builder.AppendLine($"<ows:City>{_configuration.GetValue<string>("WMTS:City")}</ows:City>");
            builder.AppendLine($"<ows:AdministrativeArea>{_configuration.GetValue<string>("WMTS:AdministrativeArea")}</ows:AdministrativeArea>");
            builder.AppendLine("<ows:PostalCode />");
            builder.AppendLine($"<ows:Country>{_configuration.GetValue<string>("WMTS:Country")}</ows:Country>");
            builder.AppendLine($"<ows:ElectronicMailAddress>{_configuration.GetValue<string>("WMTS:ElectronicMailAddress")}</ows:ElectronicMailAddress>");
            builder.AppendLine("</ows:Address>");
            builder.AppendLine("</ows:ContactInfo>");
            builder.AppendLine("</ows:ServiceContact>");
            builder.AppendLine("</ows:ServiceProvider>");
            builder.AppendLine("<ows:OperationsMetadata>");
            builder.AppendLine("<ows:Operation name=\"GetCapabilities\">");
            builder.AppendLine("<ows:DCP>");
            builder.AppendLine("<ows:HTTP>");
            builder.AppendLine($"<ows:Get xlink:href=\"{capabilitiesUri}\">");
            builder.AppendLine("<ows:Constraint name=\"GetEncoding\">");
            builder.AppendLine("<ows:AllowedValues>");
            builder.AppendLine("<ows:Value>KVP</ows:Value>");
            builder.AppendLine("</ows:AllowedValues>");
            builder.AppendLine("</ows:Constraint>");
            builder.AppendLine("</ows:Get>");
            builder.AppendLine("</ows:HTTP>");
            builder.AppendLine("</ows:DCP>");
            builder.AppendLine("</ows:Operation>");
            builder.AppendLine("<ows:Operation name=\"GetTile\">");
            builder.AppendLine("<ows:DCP>");
            builder.AppendLine("<ows:HTTP>");
            builder.AppendLine($"<ows:Get xlink:href=\"{tileUri}\">");
            builder.AppendLine("<ows:Constraint name=\"GetEncoding\">");
            builder.AppendLine("<ows:AllowedValues>");
            builder.AppendLine("<ows:Value>KVP</ows:Value>");
            builder.AppendLine("</ows:AllowedValues>");
            builder.AppendLine("</ows:Constraint>");
            builder.AppendLine("</ows:Get>");
            builder.AppendLine("</ows:HTTP>");
            builder.AppendLine("</ows:DCP>");
            builder.AppendLine("</ows:Operation>");
            builder.AppendLine("</ows:OperationsMetadata>");
            builder.AppendLine("<Contents>");
            builder.AppendLine("<Layer>");
            builder.AppendLine($"<ows:Title>{aliasName ?? wmtsListener.Layer}</ows:Title>");
            builder.AppendLine($"<ows:Abstract>WMTS service under the OGC standard</ows:Abstract>");
            builder.AppendLine($"<ows:Identifier>{wmtsListener.Layer.ToMD5String()}</ows:Identifier>");
            builder.AppendLine("<ows:WGS84BoundingBox>");

            builder.AppendLine($"<ows:LowerCorner>{wgs84Extent.MinX} {wgs84Extent.MinY}</ows:LowerCorner>");
            builder.AppendLine($"<ows:UpperCorner>{wgs84Extent.MaxX} {wgs84Extent.MaxY}</ows:UpperCorner>");
            builder.AppendLine("</ows:WGS84BoundingBox>");

            builder.AppendLine($"<ows:BoundingBox>");
            builder.AppendLine($"<ows:LowerCorner>{dstExtent.MinX} {dstExtent.MinY}</ows:LowerCorner>");
            builder.AppendLine($"<ows:UpperCorner>{dstExtent.MaxX} {dstExtent.MaxY}</ows:UpperCorner>");
            builder.AppendLine("</ows:BoundingBox>");

            builder.AppendLine("<Style isDefault=\"true\">");
            builder.AppendLine("<ows:Title>Default Style</ows:Title>");
            builder.AppendLine("<ows:Identifier>default</ows:Identifier>");
            builder.AppendLine("</Style>");
            builder.AppendLine($"<Format>{_configuration.GetValue<string>("WMTS:Format")}</Format>");
            builder.AppendLine("<TileMatrixSetLink>");
            builder.AppendLine($"<TileMatrixSet>EPSG:{epsgCode}</TileMatrixSet>");
            builder.AppendLine("</TileMatrixSetLink>");
            builder.AppendLine("</Layer>");
            builder.AppendLine("<TileMatrixSet>");
            builder.AppendLine($" <ows:Title>EPSG:{epsgCode}</ows:Title>");
            builder.AppendLine($"<ows:Abstract>EPSG:{epsgCode}</ows:Abstract>");
            builder.AppendLine($"<ows:Identifier>EPSG:{epsgCode}</ows:Identifier>");
            builder.AppendLine($"<ows:SupportedCRS>{_configuration.GetValue<string>("WMTS:TileMatrixSetSupportedCRS")}{epsgCode}</ows:SupportedCRS>");

            string TopLeftCorner = $"{dstExtent.MaxY} {dstExtent.MinX}";
            for (int level = 0; level < TileResTierPool.Instance().SuperMapLevels.Count(); level++)
            {
                var tileWidth = _configuration.GetValue<int>("WMTS:TileWidth");
                var tileHeight = _configuration.GetValue<int>("WMTS:TileHeight");
                var MatrixWidth = (int)Math.Ceiling((dstExtent.MaxX - dstExtent.MinX) / (tileWidth * TileResTierPool.Instance().SuperMapLevels[level]));
                var MatrixHeight = (int)Math.Ceiling((dstExtent.MaxY - dstExtent.MinY) / (tileHeight * TileResTierPool.Instance().SuperMapLevels[level]));

                builder.AppendLine("<TileMatrix>");
                builder.AppendLine($"<ows:Identifier>{level}</ows:Identifier>");
                builder.AppendLine($"<ScaleDenominator>{TileResTierPool.Instance().SuperMapTileScaleDenominator[level]}</ScaleDenominator>");
                builder.AppendLine($"<!-- <Resolution>{TileResTierPool.Instance().SuperMapLevels[level]}</Resolution> -->");
                builder.AppendLine($"<TopLeftCorner>{TopLeftCorner}</TopLeftCorner>");
                builder.AppendLine($"<TileWidth>{tileWidth}</TileWidth>");
                builder.AppendLine($"<TileHeight>{tileHeight}</TileHeight>");
                builder.AppendLine($"<MatrixWidth>{MatrixWidth}</MatrixWidth>");
                builder.AppendLine($"<MatrixHeight>{MatrixHeight}</MatrixHeight>");
                builder.AppendLine("</TileMatrix>");
            }

            builder.AppendLine("</TileMatrixSet>");
            builder.AppendLine("</Contents>");
            builder.AppendLine("</Capabilities>");

            return builder.ToString();
        }
    }
}
